package com.jh.paymentchannel.service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jh.paymentchannel.pojo.BranchNo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.jh.paymentchannel.business.BranchbankBussiness;
import com.jh.paymentchannel.business.TopupPayChannelBusiness;
import com.jh.paymentchannel.util.Util;
import com.jh.paymentchannel.util.xjy.Base64Util;
import com.jh.paymentchannel.util.xjy.KeyGenerator;
import com.jh.paymentchannel.util.xjy.PlatService;

import cn.jh.common.utils.DateUtil;
import net.sf.json.JSONObject;


@Controller
@EnableAutoConfiguration
public class XJYQuickpageRequest {

	private static final Logger log = LoggerFactory.getLogger(XJYQuickpageRequest.class);

	@Autowired
	private TopupPayChannelBusiness topupPayChannelBusiness;

	@Autowired
	private BranchbankBussiness branchbankBussiness;

	@Autowired
	private Util util;

	@Value("${payment.ipAddress}")
	private String ipAddress;

	@Value("${xjy.publickey}")
	private String PublicKey;

	@Value("${xjy.appid}")
	private String appId;

	@Value("${xjy.url}")
	private String getDoFormUrl;

	private static final Charset UTF_8 = StandardCharsets.UTF_8;

	private String version = "1.0.1";

	private String channelType = "88";
	
	
	
	/*
	 * 支付接口
	 * 
	 */
	@RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/xjy/pay")
	public @ResponseBody Object jfPay(HttpServletRequest request, HttpServletResponse response,
			@RequestParam(value = "ordercode") String ordercode) throws Exception {

		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");

		log.info("开始进入支付接口========================");
		Map<String, String> maps = new HashMap<String, String>();
		RestTemplate restTemplate = new RestTemplate();
		URI uri = util.getServiceUrl("transactionclear", "error url request!");
		String url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";
		MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
		requestEntity.add("order_code", ordercode);
		String result = restTemplate.postForObject(url, requestEntity, String.class);
		log.info("RESULT================" + result);
		JSONObject jsonObject;
		JSONObject resultObj;
		try {
			jsonObject = JSONObject.fromObject(result);
			resultObj = jsonObject.getJSONObject("result");
		} catch (Exception e) {
			log.error("查询订单信息出错");
			maps.put("resp_code", "failed");
			maps.put("channel_type", "jf");
			maps.put("resp_message", "没有该订单信息");
			return maps;
		}
		String userid = resultObj.getString("userid");
		// 费率
		String rate = resultObj.getString("rate");
		// 额外费用
		String extraFee = resultObj.getString("extraFee");
		// 充值卡卡号
		String bankCard = resultObj.getString("bankcard");

		String amount = resultObj.getString("amount");
		restTemplate = new RestTemplate();
		uri = util.getServiceUrl("user", "error url request!");
		url = uri.toString() + "/v1.0/user/bank/default/userid";
		requestEntity = new LinkedMultiValueMap<String, String>();
		requestEntity.add("user_id", userid);
		result = restTemplate.postForObject(url, requestEntity, String.class);

		log.info("RESULT================" + result);
		try {
			jsonObject = JSONObject.fromObject(result);
			resultObj = jsonObject.getJSONObject("result");
		} catch (Exception e) {
			log.error("查询默认结算卡出错");
			maps.put("resp_code", "failed");
			maps.put("channel_type", "jf");
			maps.put("resp_message", "查询默认结算卡有误");
			return maps;
		}

		if (resultObj.isNullObject()) {

			maps.put("resp_code", "failed");
			maps.put("channel_type", "jf");
			maps.put("resp_message", "没有结算卡");
			return maps;
		}
		// 默认提现卡卡号
		String cardNo = resultObj.getString("cardNo");
		String bankName = resultObj.getString("bankName");

		restTemplate = new RestTemplate();
		uri = util.getServiceUrl("user", "error url request!");
		url = uri.toString() + "/v1.0/user/bank/default/cardno";
		requestEntity = new LinkedMultiValueMap<String, String>();
		requestEntity.add("cardno", bankCard);
		requestEntity.add("type", "0");
		result = restTemplate.postForObject(url, requestEntity, String.class);
		log.info("接口/v1.0/user/bank/default/cardno--RESULT================" + result);
		try {
			jsonObject = JSONObject.fromObject(result);
			resultObj = jsonObject.getJSONObject("result");
		} catch (Exception e) {
			log.error("查询银行卡信息出错");
			maps.put("resp_code", "failed");
			maps.put("channel_type", "jf");
			maps.put("resp_message", "查询银行卡信息有误");
			return maps;
		}
		String phone = resultObj.getString("phone"); // 预留信用卡手机号码
		String idcard = resultObj.getString("idcard");// 身份证号
		String userName = resultObj.getString("userName");// 用户姓名

		// 根据银行名称查询得到银行信息
		BranchNo findByBankName = branchbankBussiness.findByBankName(bankName);
		// 银行总行联行号
		String inBankUnitNo = findByBankName.getBankNo();

		// 将订单总金额转换为以分为单位
		String Amount = new BigDecimal(amount).multiply(new BigDecimal("100")).setScale(0).toString();

		Double drate = Double.valueOf(rate.trim());
		log.info("drate=============" + drate);
		Double damount = Double.valueOf(amount.trim());
		log.info("damount=============" + damount);

		// 手续费
		BigDecimal bigamount = new BigDecimal(amount);
		BigDecimal bigrate = new BigDecimal(rate);
		BigDecimal bigextraFee = new BigDecimal(extraFee);
		// Bigcecimal类型的运算
		BigDecimal multiply = bigamount.multiply(bigrate);
		log.info("手续费" + multiply);
		// 小数点后2位向上进1位
		BigDecimal setScale = multiply.setScale(2, RoundingMode.CEILING);

		BigDecimal add = setScale.add(bigextraFee);
		log.info("用户总手续费======" + add);

		String Fee = new BigDecimal(add + "").multiply(new BigDecimal("100")).setScale(0).toString();
		log.info("用户总手续费(以分为单位)======" + Fee);

		Map<String, String> paramsMap = new HashMap<String, String>();

		paramsMap.put("appId", appId);
		paramsMap.put("channelType", channelType);
		paramsMap.put("version", version);
		paramsMap.put("txnAmt", Amount);
		paramsMap.put("orderId", ordercode);
		paramsMap.put("txnTime", DateUtil.getyyyyMMddHHmmssDateFormat(new Date()));

		paramsMap.put("frontUrl", ipAddress + "/v1.0/paymentchannel/topup/xjy/return_call");
		paramsMap.put("backUrl", ipAddress + "/v1.0/paymentchannel/topup/xjy/notify_call");

		paramsMap.put("accNo", bankCard);
		paramsMap.put("realName", userName);
		paramsMap.put("identityNo", idcard);
		paramsMap.put("phoneNo", phone);
		paramsMap.put("toBankName", bankName);
		paramsMap.put("toAccNo", cardNo);
		paramsMap.put("userFee", Fee);
		paramsMap.put("extFiled", "充值缴费");

		Map<String, String> reqData = new HashMap<String, String>();
		try {
			reqData.put("data", Base64Util.encode(
					KeyGenerator.encryptByPublicKey(JSON.toJSONString(paramsMap).getBytes(UTF_8), PublicKey)));
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		String requestUrl = String.format(getDoFormUrl+"/"+channelType+"/"+appId, channelType, appId);
		String html = PlatService.createAutoFormHtml(reqData, requestUrl, UTF_8);
		String jsonString;
		try {
			jsonString = PlatService.postAsString(reqData, requestUrl, UTF_8);
			log.info("jsonString====" + jsonString);
			log.info("请求支付接口成功===================");
			maps.put("resp_code", "success");
			maps.put("channel_type", "jf");
			maps.put("pageContent", jsonString);	
			return maps;
			
		} catch (Exception e) {
			log.error("请求支付接口有误==="+e);
			maps.put("resp_code", "failed");
			maps.put("channel_type", "jf");
			maps.put("resp_message", "亲，请求出错啦！请重新发起交易");
			return maps;
		}

	}

	@RequestMapping(method = RequestMethod.GET, value = "/v1.0/paymentchannel/topup/toxjybankinfo")
	public String tojfbankinfo(HttpServletRequest request, HttpServletResponse response, Model model)
			throws IOException {
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");

		String bankName = request.getParameter("bankName");// 结算卡银行名称
		String bankNo = request.getParameter("bankNo");// 结算卡卡号
		String amount = request.getParameter("amount");
		String ordercode = request.getParameter("ordercode");
		String cardType = request.getParameter("cardType");
		String ipAddress = request.getParameter("ipAddress");

		model.addAttribute("bankName", bankName);
		model.addAttribute("bankNo", bankNo);
		model.addAttribute("amount", amount);
		model.addAttribute("ordercode", ordercode);
		model.addAttribute("cardType", cardType);
		model.addAttribute("ipAddress", ipAddress);

		return "xjybankinfo";
	}

	
	// 交易同步通知
	@RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/xjy/return_call")
	public String cjReturnCallback(HttpServletRequest request, HttpServletResponse response

	) throws Exception {

		log.info("支付同步通知进来了");
		
		
        String payStatus = request.getParameter("payStatus");
        String settleStatus = request.getParameter("settleStatus");

		log.info("payStatus====="+payStatus);
		log.info("settleStatus====="+settleStatus);
		
		if("Y".equals(payStatus)&&"Y".equals(settleStatus)){
			 log.info("同步回调成功");
			  return "sdjsuccess";
		}else{
			 log.info("同步回调失败");
			  return "sdjerror";
		}
		
	}

	// 交易异步通知
	@RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/topup/xjy/notify_call")
	public void cjNotifyCallback(HttpServletRequest request, HttpServletResponse response

	) throws Exception {

		log.info("支付异步通知进来了");

		response.setHeader("Content-type", "text/html;charset=UTF-8");
        Map<String, Object> paramMap = new HashMap<String, Object>();
        Map<String, String[]> requestMap = request.getParameterMap();
        Iterator<Entry<String, String[]>> it = requestMap.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, String[]> entry = it.next();
            if (entry.getValue().length == 1) {
                paramMap.put(entry.getKey(), entry.getValue()[0]);
            } else {
                String[] values = entry.getValue();
                String value = "";
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
                paramMap.put(entry.getKey(), value);
            }
        }
        StringBuilder buffer = new StringBuilder();
        for (Entry<String, Object> entry : paramMap.entrySet()) {
            buffer.append(entry.getKey() + "|" + entry.getValue()).append("\r\n");
        }
        String data = request.getParameter("data");
        String signature = request.getParameter("signature");
        //String publicKey =  QuickPaySDKConfig.getConfig().getT0PubicKey();
        byte[] decrytData;
        try {
            decrytData = KeyGenerator.decryptByPublicKey(Base64Util.decode(data), PublicKey);
            boolean verify = KeyGenerator.verify(decrytData, PublicKey, signature);
            String rspString = new String(decrytData, UTF_8);
            com.alibaba.fastjson.JSONObject rspData = JSON.parseObject(rspString);
            if(verify){
            	
            	String orderId = rspData.getString("orderId");
                String payStatus = rspData.getString("payStatus");
                String settleStatus = rspData.getString("settleStatus");
                String queryId = rspData.getString("queryId");
                String tradeNo = rspData.getString("tradeNo");
                
                log.info("订单号   orderId===="+orderId);
                log.info("交易状态   payStatus===="+payStatus);
                log.info("出款状态   settleStatus====="+settleStatus);
                log.info("查询流水号   queryId====="+queryId);
                log.info("交易跟踪号   tradeNo====="+tradeNo);

                
                try {

    				log.info("交易： 订单结果异步通知===================");
    				if("Y".equals(payStatus)&&"Y".equals(settleStatus)){ // 订单已支付;

    					// 1、检查Amount和商户系统的订单金额是否一致
    					// 2、订单支付成功的业务逻辑处理请在本处增加（订单通知可能存在多次通知的情况，需要做多次通知的兼容处理）；
    					// 3、返回响应内容
    					
    					response.getWriter().write("success");// 回调成功
    					
    					synchronized (this) {
    						// **更新订单状态*//*
    						// **调用下单，需要得到用户的订单信息*//*
    						RestTemplate restTemplate = new RestTemplate();

    						URI uri = util.getServiceUrl("transactionclear", "error url request!");
    						String url = uri.toString() + "/v1.0/transactionclear/payment/update";

    						// **根据的用户手机号码查询用户的基本信息*//*
    						MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
    						requestEntity.add("status", "1");
    						requestEntity.add("third_code", queryId);
    						requestEntity.add("order_code", orderId);
    						String result = restTemplate.postForObject(url, requestEntity, String.class);

    						log.info("订单状态修改成功===================");

    						/*// **判断是否有外放的通道的处理， 如果有那么继续回调外放哦*//*
    						uri = util.getServiceUrl("transactionclear", "error url request!");
    						url = uri.toString() + "/v1.0/transactionclear/payment/query/ordercode";

    						requestEntity = new LinkedMultiValueMap<String, String>();
    						requestEntity.add("order_code", orderId);
    						result = restTemplate.postForObject(url, requestEntity, String.class);

    						JSONObject jsonObject = JSONObject.fromObject(result);
    						JSONObject resultObj = jsonObject.getJSONObject("result");
    						String outMerOrdercode = resultObj.getString("outMerOrdercode");
    						String orderdesc = resultObj.getString("desc");
    						String phone = resultObj.getString("phone");
    						String tranamount = resultObj.getString("amount");
    						String channelTag = resultObj.getString("channelTag");
    						String notifyURL = resultObj.getString("outNotifyUrl");
    						if (outMerOrdercode != null && !outMerOrdercode.equalsIgnoreCase("")) {
    							uri = util.getServiceUrl("channel", "error url request!");
    							url = uri.toString() + "/v1.0/channel/callback/yilian/notify_call";
    							requestEntity = new LinkedMultiValueMap<String, String>();
    							requestEntity.add("merchant_no", phone);
    							requestEntity.add("amount", tranamount);
    							requestEntity.add("channel_tag", channelTag);
    							requestEntity.add("order_desc", URLEncoder.encode(orderdesc, "UTF-8"));
    							requestEntity.add("order_code", outMerOrdercode);
    							requestEntity.add("sys_order", orderId);
    							requestEntity.add("notify_url", URLEncoder.encode(notifyURL, "UTF-8"));
    							result = restTemplate.postForObject(url, requestEntity, String.class);
    						}*/

    						log.info("订单已支付!");
    						
    					}
    				} else {
    					// 1、订单支付失败的业务逻辑处理请在本处增加（订单通知可能存在多次通知的情况，需要做多次通知的兼容处理，避免成功后又修改为失败）；
    					// 2、返回响应内容

    					log.info("订单支付失败!");
    				}
    			} catch (Exception e) {
    				log.error(e.getMessage());
    			}
    			log.info("-----处理完成----");
                
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
       

	}

}